	.XLIST
	TITLE	CCP
	SUBTTL	CP/M Console Command Processor
	.LIST
	.Z80

	.COMMENT \
This is a commented listing of CP/M 2.2, the CCP.
Since it is the result of a disassembly into Zilog mnemonics,
any inaccuracies in the comments are to be attributed to my stupidity.
Hopefully, there aren't any, but you never can tell...

This is phase I of a project, phase II being rewriting the blasted
thing for the Z80.
	\
	MACLIB	CPMEQUS.LIB
	
	ENTRY	CCPSER		;SERIAL NUMBERS ARE HERE
	EXTRN	DOSSER

	PAGE	60

	.PHASE	CCPBASE

CCP:
	JP	PRICCP

	JP	ALTCCP

	.COMMENT \
This is the main console input buffer
for the CCP.  Used for command input
and is checked for input on boot.
This last is the basic reason the
REBOOT program works.
 \

CMDBUF:
	DEFB	07FH	;COMMAND LINES MAX OUT AT 127 CHARACTERS
CMDLEN:
	DEFB	0	;CURRENT NUMBER OF CHARS IN BUFFER
CMDTXT:
	DEFB	"                COPYRIGHT (C) 1979, DIGITAL RESEARCH  "
	DEFZ	73
	DEFB	0	;GUARD BYTE, IN CASE OF BUFFER OVERRUN


FSTPTR:			;TEMP STORAGE FOR POINTERS TO CMD BUFFER
	DEFW	CMDTXT
NXTPTR:
	DEFW	0

OTCONS:
	LD	E,A
	LD	C,2	;CONSOLE OUTPUT, RAW
	JP	BDOS

OTCSBC:
	PUSH	BC
	CALL	OTCONS	;CONSOLE OUTPUT, SAVES BC.
	POP	BC	
	RET

OTCRLF:
	LD	A,00DH	;OUTPUT CR-LF COMBO TO CONSOLE
	CALL	OTCSBC	;SAVING ESSENTIAL REGISTERS
	LD	A,00AH
	JP	OTCSBC

OTSPAC:
	LD	A," "	;OUTPUT SPACE TO CONSOLE
	JP	OTCSBC	;SAVING ESSENTIAL REGISTERS

OTNTST:
	PUSH	BC	;PRINTS NULL-TERMINATED STRING
	CALL	OTCRLF	;POINTED TO BY BC, PRECEDED BY
	POP	HL	;BY A CR-LF,
OTNSTR:
	LD	A,(HL)	;SAME BUT STRING POINTED TO BY
	OR	A	;HL,AND NO CR-LF
	RET	Z	;USED WHEN A BUFFER IS FILLED
	INC	HL	;ESPECIALLY IN CCP DURING 
	PUSH	HL	;COMMAND INPUT
	CALL	OTCONS
	POP	HL
	JP	OTNSTR

RSDSKC:
	LD	C,13	;RESET DISK SYSTEM BDOS CALL
	JP	BDOS

SLDSKC:
	LD	E,A
	LD	C,14	;SELECT DISK BDOS CALL
	JP	BDOS

BDSSTR:
	CALL	BDOS	;CALLS BDOS AND STORES RETURNED
	LD	(RETCOD),A	;VALUE FOR FCNS W/SUCH
	INC	A	;SETS Z/NZ
	RET

OPNFIL:
	LD	C,15	;OPEN FILE BDOS CALL
	JP	BDSSTR

OPNWRK:
	XOR	A		;CLEAR NEXT RECORD FIELD
	LD	(WRKFCB+32),A	;OF THE WORK FCB AND OPEN
	LD	DE,WRKFCB	;OPEN IT, STORING THE RETURN
	JP	OPNFIL		;RETURN CODE.

CLSFIL:
	LD	C,16	;CLOSE FILE BDOS CALL
	JP	BDSSTR

SRCHFFL:
	LD	C,17	;SEARCH FIRST BDOS CALL
	JP	BDSSTR

SRCHNFL:
	LD	C,18	;SEARCH NEXT BDOS CALL
	JP	BDSSTR

SCHWRK:
	LD	DE,WRKFCB	;SEARCH FOR WORK FCB
	JP	SRCHFFL

DELFIL:
	LD	C,19	;DELETE FILE FUNCTION
	JP	BDOS

BDSZNZ:
	CALL	BDOS	;CALL BDOS, SET Z,NZ FOR SUCCESS
	OR	A	;OR FAILURE
	RET

REDFIL:
	LD	C,20	;READ SEQUENTIAL
	JP	BDSZNZ

REDWRK:
	LD	DE,WRKFCB	;READ THE WORK FILE
	JP	REDFIL

WRTFIL:
	LD	C,21	;WRITE SEQUENTIAL
	JP	BDSZNZ

MAKFIL:
	LD	C,22	;MAKE FILE
	JP	BDSSTR

RENFIL:
	LD	C,23	;RENAME FILE
	JP	BDOS

GETUSR:
	LD	E,0FFH	;QUERY USER CODE
SETUSR:
	LD	C,32	;SET/GET USER CODE
	JP	BDOS

SDFUSR:
	CALL	GETUSR		;THIS ROUTINE SETS THE CURRENT USER CODE
	ADD	A,A		;INTO THE DEFAULT DRIVE BYTE WHILE
	ADD	A,A		;LEAVING THE PRIVATE COPY OF THE DEFAULT
	ADD	A,A		;DRIVE ALONE THUS MAINTAINING THE USER
	ADD	A,A		;ON WHICHEVER DRIVE HE'S CHOSEN
	LD	HL,LOGDSK
	OR	(HL)
	LD	(DEFDRV),A
	RET

SUSR0D:
	LD	A,(LOGDSK)	;SETS BACK TO USER 0
	LD	(DEFDRV),A
	RET

TOUPPR:
	CP	"a"	;Converts lower case to upper case
	RET	C
	CP	"z"+1
	RET	NC
	AND	05FH
	RET
	PAGE
GETCMD:	;GETS A COMMAND FROM SUBMIT FILE OR CONSOLE
	LD	A,(SUBFLG)	;ARE WE IN A SUBMIT CHAIN?
	OR	A
	JP	Z,..GC1		;NOPE, GO LOOK AT THE CONSOLE
	LD	A,(LOGDSK)
	OR	A		;CHANGE SELECTED DISK TO 0
	LD	A,0
	CALL	NZ,SLDSKC
	LD	DE,SUBFCB	;OPEN THE "$$$.SUB" FILE
	CALL	OPNFIL
	JP	Z,..GC1		;IF ERROR, STOP AND GO TO CONSOLE
	LD	A,(SUBFCB+15)	;GET NUMBER OF SECTORS IN FILE
	DEC	A
	LD	(SUBFCB+32),A	;NOTE THE $$$.SUB FILE IS READ
	LD	DE,SUBFCB	;BASS-ACKWARDS!!!!!
	CALL	REDFIL
	JP	NZ,..GC1	;AGAIN, IF ERROR QUIT 
	LD	DE,CMDLEN
	LD	HL,TBUFF
	LD	B,128		;MOVE THE RECORD TO THE CCP 
	CALL	MOVSTR		;COMMAND BUFFER.  THIS SHOULD TELL
	LD	HL,SUBFCB+14	; WHAT FORMAT A SUB FILE IS!!!!!
	LD	(HL),0		;CLEAR THE S2 BYTE
	INC	HL		;REDUCE THE FILE SIZE BY 1
	DEC	(HL)
	LD	DE,SUBFCB
	CALL	CLSFIL		;CLOSE IT
	JP	Z,..GC1		;SAME OLD, SAME OLD....
	LD	A,(LOGDSK)	;CHANGE THE DISK LOGGED BACK
	OR	A
	CALL	NZ,SLDSKC
	LD	HL,CMDTXT
	CALL	OTNSTR		;TYPE THE COMMAND ON THE CONSOLE
	CALL	CHKCONS		;CHECK IF USER WANTS TO ABORT
	JP	Z,..GC2		; NO, PROCEED...
	CALL	CLRSUB		;CLEAR SUBMIT CHAIN
	JP	PROMPT		; AND LEAVE
..GC1:
	CALL	CLRSUB		;CLEAR SUBMIT CHAIN
	CALL	SDFUSR		;SET THE DEFAULT USER
	LD	C,10
	LD	DE,CMDBUF	; AND GET A COMMAND MANUALLY!!!!!
	CALL	BDOS
	CALL	SUSR0D		; SET THE DEFAULT USER TO 0
..GC2:
	LD	HL,CMDLEN	;CONVERT THE COMMAND TO ALL UPPER CASE
	LD	B,(HL)		; LENGTH OF COMMAND
..GC3:
	INC	HL
	LD	A,B
	OR	A
	JP	Z,..GC4		;DONE
	LD	A,(HL)
	CALL	TOUPPR
	LD	(HL),A
	DEC	B
	JP	..GC3
..GC4:
	LD	(HL),A
	LD	HL,CMDTXT
	LD	(FSTPTR),HL	;SAVE START ADDR OF COMMAND
	RET
	PAGE
CHKCONS:
	LD	C,11	;IS THERE A CHARACTER READY
	CALL	BDOS	;AT THE CONSOLE?
	OR	A
	RET	Z	;NO, GO AWAY. Z SET
	LD	C,1	;YEP. GET IT
	CALL	BDOS
	OR	A	;SET NZ, HOPEFULLY(IF ITS A NULL,WATCH OUT)
	RET

GCURDSK:
	LD	C,25	;GET CURRENT DISK
	JP	BDOS

DMA2TBF:
	LD	DE,TBUFF	;SET DMA TO TBUFF
DMA2DE:
	LD	C,26	;SET DMA ADDRESS
	JP	BDOS

CLRSUB:
	LD	HL,SUBFLG	;CLEAR SUBMIT FLAG IF SET
	LD	A,(HL)
	OR	A
	RET	Z
	LD	(HL),0
	XOR	A		;SELECT DRIVE A
	CALL	SLDSKC
	LD	DE,SUBFCB
	CALL	DELFIL		;DELETE "$$$.SUB" 
	LD	A,(LOGDSK)
	JP	SLDSKC		;AND RESET DEFAULT DISK

CHKSER:
	LD	DE,CCPSER	;COMPARES SERIAL NUMBERS
	LD	HL,DOSSER	;IN CCP AND BDOS.  IF THEY DISAGREE,
	LD	B,006H		;BLOW THE SYSTEM BY JUMPING TO ZAPPER
..CH1:
	LD	A,(DE)
	CP	(HL)
	JP	NZ,ZAPPER
	INC	DE
	INC	HL
	DEC	B
	JP	NZ,..CH1
	RET

BADCMD:				;THIS ROUTINE PRINTS A COMMAND, FCB,ETC
	CALL	OTCRLF		;WHEN THERE IS AN ERROR.  PRINTS "?"
	LD	HL,(NXTPTR)	;CLEARS SUBMIT CHAINS, AND GOES BACK TO GET A
..BD1:				;NEW COMMAND
	LD	A,(HL)
	CP	" "
	JP	Z,..BD2
	OR	A
	JP	Z,..BD2
	PUSH	HL
	CALL	OTCONS
	POP	HL
	INC	HL
	JP	..BD1
..BD2:
	LD	A,"?"
	CALL	OTCONS
	CALL	OTCRLF
	CALL	CLRSUB
	JP	PROMPT

TSTDLM:				;TESTS FOR VARIOUS DELIMITERS
	LD	A,(DE)
	OR	A
	RET	Z
	CP	" "
	JP	C,BADCMD
	RET	Z
	CP	"="
	RET	Z
	CP	"_"
	RET	Z
	CP	"."
	RET	Z
	CP	":"
	RET	Z
	CP	";"
	RET	Z
	CP	"<"
	RET	Z
	CP	">"
	RET	Z
	RET			;DUMB!!!!

SKIPSP:
	LD	A,(DE)
	OR	A
	RET	Z
	CP	" "
	RET	NZ
	INC	DE
	JP	SKIPSP

ADA2HL:
	ADD	A,L
	LD	L,A
	RET	NC
	INC	H
	RET
	PAGE
PARSEWRK:		;PARSES COMMAND LINE TEXT INTO THE WORK FCB
	LD	A,0	;STARTING AT THE "A'TH" LOCATION OF THE FCB
PARSE:			;AND THE LAST USED POSITION ON THE COMMAND LINE
	LD	HL,WRKFCB	;RETURNS A = NUMBER OF ? IN PARSED FCB
	CALL	ADA2HL		;Z,NZ FOR NON-AMBIG FILE NAMES, AMBIG
	PUSH	HL
	PUSH	HL
	XOR	A
	LD	(USEDSK),A
	LD	HL,(FSTPTR)
	EX	DE,HL
	CALL	SKIPSP
	EX	DE,HL
	LD	(NXTPTR),HL
	EX	DE,HL
	POP	HL
	LD	A,(DE)
	OR	A
	JP	Z,..PF1
	SBC	A,040H
	LD	B,A
	INC	DE
	LD	A,(DE)
	CP	":"
	JP	Z,..PF2
	DEC	DE
..PF1:
	LD	A,(LOGDSK)
	LD	(HL),A
	JP	..PF3
..PF2:
	LD	A,B
	LD	(USEDSK),A
	LD	(HL),B
	INC	DE
..PF3:
	LD	B,8
..PF4:
	CALL	TSTDLM
	JP	Z,..PF8
	INC	HL
	CP	"*"
	JP	NZ,..PF5
	LD	(HL),"?"
	JP	..PF6
..PF5:
	LD	(HL),A
	INC	DE
..PF6:
	DEC	B
	JP	NZ,..PF4
..PF7:
	CALL	TSTDLM
	JP	Z,..PF9
	INC	DE
	JP	..PF7
..PF8:
	INC	HL
	LD	(HL)," "
	DEC	B
	JP	NZ,..PF8
..PF9:
	LD	B,3
	CP	"."
	JP	NZ,..PF14
	INC	DE
..PF10:
	CALL	TSTDLM
	JP	Z,..PF14
	INC	HL
	CP	"*"
	JP	NZ,..PF11
	LD	(HL),"?"
	JP	..PF12
..PF11:
	LD	(HL),A
	INC	DE
..PF12:
	DEC	B
	JP	NZ,..PF10
..PF13:
	CALL	TSTDLM
	JP	Z,..PF15
	INC	DE
	JP	..PF13
..PF14:
	INC	HL
	LD	(HL)," "
	DEC	B
	JP	NZ,..PF14
..PF15:
	LD	B,3
..PF16:
	INC	HL
	LD	(HL),0
	DEC	B
	JP	NZ,..PF16
	EX	DE,HL
	LD	(FSTPTR),HL
	POP	HL
	LD	BC,11
..PF17:
	INC	HL
	LD	A,(HL)
	CP	"?"
	JP	NZ,..PF18
	INC	B
..PF18:
	DEC	C
	JP	NZ,..PF17
	LD	A,B
	OR	A
	RET
	PAGE
CMDTBL:
	DEFM	"DIR "
	DEFM	"ERA "
	DEFM	"TYPE"
	DEFM	"SAVE"
	DEFM	"REN "
	DEFM	"USER"

	.COMMENT *
Serial number time, again,
kiddies.  This thing is 
compared with the one in the
BDOS and the ZAPPER routine
called if they differ.
	*

CCPSER:
	DEFB	0
	DEFB	22	; = 2.2 = VERSION NUMBER!!!!
	DEFB	0
	DEFB	0
	DEFB	009H
	DEFB	070H

CMDECD:
	LD	HL,CMDTBL
	LD	C,0
..CD1:
	LD	A,C
	CP	6
	RET	NC
	LD	DE,WRKFCB+1
	LD	B,4
..CD2:
	LD	A,(DE)
	CP	(HL)
	JP	NZ,..CD3
	INC	DE
	INC	HL
	DEC	B
	JP	NZ,..CD2
	LD	A,(DE)
	CP	" "
	JP	NZ,..CD4
	LD	A,C
	RET
..CD3:
	INC	HL
	DEC	B
	JP	NZ,..CD3
..CD4:
	INC	C
	JP	..CD1
	PAGE
;	THIS IS THE ACTUAL BEGINNING OF THE CCP

ALTCCP:	;ALTERNATE ENTRY
	XOR	A
	LD	(CMDLEN),A
PRICCP:	;PRIMARY ENTRY
	LD	SP,SUBFLG
	PUSH	BC
	LD	A,C
	RRA
	RRA
	RRA
	RRA
	AND	00FH
	LD	E,A
	CALL	SETUSR
	CALL	RSDSKC
	LD	(SUBFLG),A
	POP	BC
	LD	A,C
	AND	00FH
	LD	(LOGDSK),A
	CALL	SLDSKC
	LD	A,(CMDLEN)
	OR	A
	JP	NZ,PRCSCMD
PROMPT:
	LD	SP,SUBFLG
	CALL	OTCRLF
	CALL	GCURDSK
	ADD	A,"A"
	CALL	OTCONS
	LD	A,">"
	CALL	OTCONS
	CALL	GETCMD
PRCSCMD:
	LD	DE,TBUFF
	CALL	DMA2DE
	CALL	GCURDSK
	LD	(LOGDSK),A
	CALL	PARSEWRK
	CALL	NZ,BADCMD
	LD	A,(USEDSK)
	OR	A
	JP	NZ,COMRTN
	CALL	CMDECD
	LD	HL,CMDRTNS
	LD	E,A
	LD	D,0
	ADD	HL,DE
	ADD	HL,DE
	LD	A,(HL)
	INC	HL
	LD	H,(HL)
	LD	L,A
	JP	(HL)

CMDRTNS:
	DEFW	DIRRTN
	DEFW	ERARTN
	DEFW	TYPRTN
	DEFW	SAVRTN
	DEFW	RENRTN
	DEFW	USERRTN
	DEFW	COMRTN

ZAPPER:
	LD	HL,076F3H	;LOADS INSTRUCTION SEQUENCE
	LD	(CCP),HL	;"DI, HALT" AND THEN GOES THERE
	LD	HL,CCP		;CALLED IF SERIAL NUMBERS OF BDOS
	JP	(HL)		;AND CCP DON'T MATCH.

RDERRM:
	LD	BC,RDMSG
	JP	OTNTST

RDMSG:
	DEFB	"Read error",0

NOFILM:
	LD	BC,NFLMSG
	JP	OTNTST

NFLMSG:
	DEFB	"No file",0
	PAGE
GETDEC:			;GETS DECIMAL FROM COMMAND LINE INTO A
	CALL	PARSEWRK
	LD	A,(USEDSK)
	OR	A
	JP	NZ,BADCMD
	LD	HL,WRKFCB+1
	LD	BC,11
..GD1:
	LD	A,(HL)
	CP	" "
	JP	Z,..GD2
	INC	HL
	SUB	"0"
	CP	10
	JP	NC,BADCMD
	LD	D,A
	LD	A,B
	AND	0E0H
	JP	NZ,BADCMD
	LD	A,B
	RLCA
	RLCA
	RLCA
	ADD	A,B
	JP	C,BADCMD
	ADD	A,B
	JP	C,BADCMD
	ADD	A,D
	JP	C,BADCMD
	LD	B,A
	DEC	C
	JP	NZ,..GD1
	RET
..GD2:
	LD	A,(HL)
	CP	" "
	JP	NZ,BADCMD
	INC	HL
	DEC	C
	JP	NZ,..GD2
	LD	A,B
	RET

MOV3:
	LD	B,003H
MOVSTR:
	LD	A,(HL)
	LD	(DE),A
	INC	HL
	INC	DE
	DEC	B
	JP	NZ,MOVSTR
	RET

ADACHL:
	LD	HL,00080H
	ADD	A,C
	CALL	ADA2HL
	LD	A,(HL)
	RET

SELUSE:
	XOR	A		;SELECT DISK TO USE BASED ON
	LD	(WRKFCB),A	;WHAT DISK IS SPECIFIED IN COMMAND LINE
	LD	A,(USEDSK)
	OR	A
	RET	Z
	DEC	A
	LD	HL,LOGDSK
	CP	(HL)		;IF LOGGED DISK DIFFERENT, SELECT USE DISK
	RET	Z
	JP	SLDSKC

SELLOG:
	LD	A,(USEDSK)	;THIS ROUTINE RE-SELECTS THE LOGGED DISK, IF
	OR	A		;DIFFERENT FROM THE ONE IN USE
	RET	Z
	DEC	A
	LD	HL,LOGDSK
	CP	(HL)
	RET	Z
	LD	A,(LOGDSK)
	JP	SLDSKC
	PAGE
DIRRTN:	; THIS ROUTINE HANDLES THE DIR COMMAND
	CALL	PARSEWRK
	CALL	SELUSE
	LD	HL,WRKFCB+1
	LD	A,(HL)
	CP	" "
	JP	NZ,..DR2
	LD	B,11
..DR1:
	LD	(HL),"?"	;FILL WORK FCB WITH ?
	INC	HL		;FOR ALL DIRECTORY ENTRIES TO WHOW
	DEC	B
	JP	NZ,..DR1
..DR2:
	LD	E,0
	PUSH	DE
	CALL	SCHWRK		; SEARCH FOR A MATCH
	CALL	Z,NOFILM
..DR3:
	JP	Z,..DR11
	LD	A,(RETCOD)	;GET ENTRY NUMBER FOR MATCHING FILE
	RRCA
	RRCA
	RRCA
	AND	060H
	LD	C,A	;C HAS OFFSET TO DIRECTORY ENTRY
	LD	A,00AH	;GET THE DIR ATTRIBUTE BIT
	CALL	ADACHL
	RLA		;IF SET, DON'T SHOW THE FILE
	JP	C,..DR10
	POP	DE
	LD	A,E
	INC	E
	PUSH	DE
	AND	003H		;FOUR DIRECTORY ENTRIES PER LINE
	PUSH	AF
	JP	NZ,..DR4
	CALL	OTCRLF
	PUSH	BC
	CALL	GCURDSK
	POP	BC
	ADD	A,"A"		;WITH CURRENT DISK LABELING
	CALL	OTCSBC
	LD	A,":"
	CALL	OTCSBC
	JP	..DR5
..DR4:
	CALL	OTSPAC
	LD	A,":"
	CALL	OTCSBC		;PUT A DIVIDER BETWEEN ENTRIES
..DR5:
	CALL	OTSPAC
	LD	B,1
..DR6:
	LD	A,B
	CALL	ADACHL
	AND	07FH
	CP	" "
	JP	NZ,..DR8
	POP	AF
	PUSH	AF
	CP	003H
	JP	NZ,..DR7
	LD	A,009H
	CALL	ADACHL
	AND	07FH		;IS THERE AN EXT?
	CP	" "
	JP	Z,..DR9		;NOPE
..DR7:
	LD	A," "
..DR8:
	CALL	OTCSBC
	INC	B
	LD	A,B
	CP	12		;END OF ENTRY?
	JP	NC,..DR9	;YEP
	CP	9		;END OF FILENAME?
	JP	NZ,..DR6	;NOPE
	CALL	OTSPAC		;SPACE AND GO FOR NEXT
	JP	..DR6
..DR9:
	POP	AF
..DR10:
	CALL	CHKCONS		;ABORT THE LISTING?
	JP	NZ,..DR11
	CALL	SRCHNFL		;NO, GO FOR NEXT FILE
	JP	..DR3
..DR11:
	POP	DE
	JP	CMDXIT
	PAGE
ERARTN:	; THIS IS THE ERA COMMAND HANDLER
	CALL	PARSEWRK
	CP	11		;ERASE ALL???
	JP	NZ,..ER1	; NO
	LD	BC,VERERA	;YES,GET VERIFICATION
	CALL	OTNTST
	CALL	GETCMD
	LD	HL,CMDLEN
	DEC	(HL)
	JP	NZ,PROMPT	;MORE THAN ONE CHAR OR NONE, IGNORE
	INC	HL
	LD	A,(HL)
	CP	"Y"
	JP	NZ,PROMPT
	INC	HL
	LD	(FSTPTR),HL	;HL = CMDTXT AT THIS POINT
..ER1:
	CALL	SELUSE		;SELECT THE DISK TO USE
	LD	DE,WRKFCB
	CALL	DELFIL		;ZAP!!!!
	INC	A
	CALL	Z,NOFILM		;ANTHING WRONG?
	JP	CMDXIT

VERERA:
	DEFB	"ALL (Y/N)?",0
	PAGE
TYPRTN:	; THIS IS THE TYPE COMMAND HANDLER
	CALL	PARSEWRK
	JP	NZ,BADCMD	;NO AMBIGUOUS 'TYPE'
	CALL	SELUSE
	CALL	OPNWRK
	JP	Z,..TP4
	CALL	OTCRLF
	LD	HL,CHRCNT
	LD	(HL),0FFH
..TP1:
	LD	HL,CHRCNT
	LD	A,(HL)
	CP	080H
	JP	C,..TP2
	PUSH	HL
	CALL	REDWRK
	POP	HL
	JP	NZ,..TP3
	XOR	A
	LD	(HL),A
..TP2:
	INC	(HL)
	LD	HL,TBUFF
	CALL	ADA2HL
	LD	A,(HL)
	CP	01AH
	JP	Z,CMDXIT
	CALL	OTCONS
	CALL	CHKCONS
	JP	NZ,CMDXIT
	JP	..TP1
..TP3:
	DEC	A
	JP	Z,CMDXIT
	CALL	RDERRM
..TP4:
	CALL	SELLOG
	JP	BADCMD
	PAGE
SAVRTN:	; THIS IS THE SAVE COMMAND HANDLER 
	CALL	GETDEC
	PUSH	AF		;GET NUMBER OF PAGES TO SAVE
	CALL	PARSEWRK	;GET FILE
	JP	NZ,BADCMD	;MAY NOT SAVE AMBIGUOUS
	CALL	SELUSE
	LD	DE,WRKFCB	;DELETE OLD VERSION
	PUSH	DE
	CALL	DELFIL
	POP	DE
	CALL	MAKFIL		;MAKE NEW VERSION
	JP	Z,..SV3		
	XOR	A
	LD	(WRKFCB+32),A	;INIT FCB
	POP	AF
	LD	L,A
	LD	H,0
	ADD	HL,HL		;NUMBER OF RECORDS
	LD	DE,TPA		;SAVE AREA START
..SV1:
	LD	A,H
	OR	L		;DONE??
	JP	Z,..SV2
	DEC	HL
	PUSH	HL
	LD	HL,00080H
	ADD	HL,DE
	PUSH	HL
	CALL	DMA2DE		;POINT TO SAVE AREA
	LD	DE,WRKFCB
	CALL	WRTFIL		;WRITE IT
	POP	DE
	POP	HL		;NEW POINTERS
	JP	NZ,..SV3	;WHOOPS!!!!
	JP	..SV1		;GO BACK FOR MORE
..SV2:
	LD	DE,WRKFCB	;CLOSE IT
	CALL	CLSFIL
	INC	A
	JP	NZ,..SV4	;ANYTHING GO WRONG
..SV3:
	LD	BC,NORUMM	;YEP.  SAY SOMETHING ABOUT IT.
	CALL	OTNTST
..SV4:
	CALL	DMA2TBF		;RESET DMA ADDR
	JP	CMDXIT		;AND LEAVE

NORUMM:
	DEFB	"No space",0
	PAGE
RENRTN:	;THIS IS THE RENAME COMMAND HANDLER
	CALL	PARSEWRK
	JP	NZ,BADCMD	;NO AMBIGUOUS RENAMES
	LD	A,(USEDSK)
	PUSH	AF
	CALL	SELUSE
	CALL	SCHWRK		;FILE ALREADY THERE?
	JP	NZ,..RN5	;YEAH, TELL THE OPERATOR
	LD	HL,WRKFCB
	LD	DE,WRKFCB+16
	LD	B,16	
	CALL	MOVSTR		;SET UP FOR RENAME FUNCTION
	LD	HL,(FSTPTR)
	EX	DE,HL
	CALL	SKIPSP
	CP	"="		;STANDARD DELIM
	JP	Z,..RN1
	CP	"_"		;BUT THIS WORKS TOO
	JP	NZ,..RN4
..RN1:
	EX	DE,HL
	INC	HL
	LD	(FSTPTR),HL
	CALL	PARSEWRK
	JP	NZ,..RN4	;NO AMBIGUITIES
	POP	AF
	LD	B,A
	LD	HL,USEDSK
	LD	A,(HL)
	OR	A
	JP	Z,..RN2
	CP	B
	LD	(HL),B
	JP	NZ,..RN4
..RN2:
	LD	(HL),B
	XOR	A
	LD	(WRKFCB),A
	CALL	SCHWRK
	JP	Z,..RN3		;IS THERE A FILE TO BE RENAMED?
	LD	DE,WRKFCB
	CALL	RENFIL		;DO IT!!!
	JP	CMDXIT
..RN3:
	CALL	NOFILM		;TELL OP SOMETHING WRONG
	JP	CMDXIT
..RN4:
	CALL	SELLOG
	JP	BADCMD
..RN5:
	LD	BC,FILEIS	
	CALL	OTNTST
	JP	CMDXIT

FILEIS:
	DEFB	"File exists",0
	PAGE
USERRTN: ; THIS SETS THE USER NUMBER PER USER COMMAND
	CALL	GETDEC
	CP	16		;MAX USER NUMBER + 1
	JP	NC,BADCMD
	LD	E,A
	LD	A,(WRKFCB+1)
	CP	" "
	JP	Z,BADCMD
	CALL	SETUSR
	JP	COMXIT
	PAGE
COMRTN:	; THIS LOADS AND EXECUTES TRANSIENTS (I.E.,"COM" FILES)
	CALL	CHKSER
	LD	A,(WRKFCB+1)
	CP	" "
	JP	NZ,..CM1
	LD	A,(USEDSK)
	OR	A
	JP	Z,COMXIT
	DEC	A
	LD	(LOGDSK),A
	CALL	SUSR0D
	CALL	SLDSKC
	JP	COMXIT
..CM1:
	LD	DE,WRKFCB+9
	LD	A,(DE)
	CP	" "
	JP	NZ,BADCMD
	PUSH	DE
	CALL	SELUSE
	POP	DE
	LD	HL,TDB83
	CALL	MOV3
	CALL	OPNWRK
	JP	Z,..CM8
	LD	HL,TPA
..CM2:
	PUSH	HL
	EX	DE,HL
	CALL	DMA2DE
	LD	DE,WRKFCB
	CALL	REDFIL
	JP	NZ,..CM3
	POP	HL
	LD	DE,00080H
	ADD	HL,DE
	LD	DE,CCP
	LD	A,L
	SUB	E
	LD	A,H
	SBC	A,D
	JP	NC,..CM9
	JP	..CM2
..CM3:
	POP	HL
	DEC	A
	JP	NZ,..CM9
	CALL	SELLOG
	CALL	PARSEWRK
	LD	HL,USEDSK
	PUSH	HL
	LD	A,(HL)
	LD	(WRKFCB),A
	LD	A,16
	CALL	PARSE
	POP	HL
	LD	A,(HL)
	LD	(WRKFCB+16),A
	XOR	A
	LD	(WRKFCB+32),A
	LD	DE,TFCB
	LD	HL,WRKFCB
	LD	B,33
	CALL	MOVSTR
	LD	HL,CMDTXT
..CM4:
	LD	A,(HL)
	OR	A
	JP	Z,..CM5
	CP	" "
	JP	Z,..CM5
	INC	HL
	JP	..CM4
..CM5:
	LD	B,0
	LD	DE,TBUFF+1
..CM6:
	LD	A,(HL)
	LD	(DE),A
	OR	A
	JP	Z,..CM7
	INC	B
	INC	HL
	INC	DE
	JP	..CM6
..CM7:
	LD	A,B
	LD	(TBUFF),A
	CALL	OTCRLF
	CALL	DMA2TBF
	CALL	SDFUSR
	CALL	TPA		;Execute transient command!
	LD	SP,SUBFLG
	CALL	SUSR0D
	CALL	SLDSKC
	JP	PROMPT
..CM8:
	CALL	SELLOG
	JP	BADCMD
..CM9:
	LD	BC,TDB7A
	CALL	OTNTST
	JP	CMDXIT

TDB7A:
	DEFB	"Bad Load",0

TDB83:
	DEFB	"COM"	;Extension for prog files
	PAGE
;GENERAL EXIT ROUTINES
;
;THE BUILTIN COMMANDS FIRST SELECT THE LOGGED DISK
;THEN EVERYTHING CHECKS IF THERE WAS SOME CNTL CHAR
;LEFT OR THE DISK TO USE WAS NOT CLEARED.

CMDXIT:
	CALL	SELLOG		
COMXIT:
	CALL	PARSEWRK
	LD	A,(WRKFCB+1)
	SUB	020H
	LD	HL,USEDSK
	OR	(HL)
	JP	NZ,BADCMD
	JP	PROMPT
	PAGE
;	DATA AREAS, STACK, FCB'S, ETC.



	DEFZ	16		;STACK AREA

SUBFLG:
	DEFB	0		;INPUT FROM SUBMIT FILE OR NOT

SUBFCB:
	DEFB	0,"$$$     SUB"	;FCB FOR THE SUBMIT FILE
	DEFZ	21

WRKFCB:
	DEFZ	33		;GENERAL PURPOSE FCB FOR THE VARIOUS COMMANDS
				;PROVIDES WORK AREA FOR BUILDING DEFAULT 
				;FCB'S FOR COMMAND LINE, ETC. 

RETCOD:
	DEFB	0		;HOLDS RETURN CODE FOR BDOS CALLS

LOGDSK:
	DEFB	0		;HOLDS PRIVATE VALUE OF CURRENTLY LOGGED DISK

USEDSK:				;HOLDS VALUE OF DISK IN USE
	DEFB	0

CHRCNT:
	DEFB	0		;USED IN TYPE ROUTINE

	DEFZ	14

LENGTH	EQU	$-CCP		;SHOULD BE 2048

	.DEPHASE

	END
